import fs from 'node:fs';
import path from 'node:path';
import Url from 'node:url';
import { PackageJson } from 'type-fest';
import { prompt, toStringify } from '../utils';
import { findPackageJson } from '../utils/npm-package';
import JenkinsApi from './jenkins';
import { getConfig, stdoutResult } from './utils';

const SAVE_PATH = '.qps-jenkins';
const getFilePath = () => path.join(process.env.HOME, SAVE_PATH);

type UserInfoType = {
  password: string;
  userName: string;
};

export type DeployType = {
  branch?: string;
  name?: string;
  log?: boolean;
};

export default async function deploy(env: string, options: DeployType) {
  if (!env) {
    throw new Error(`请指定发布环境:'dev' | 'test' | 'prod'`);
  }
  const str = findPackageJson();
  const pkg = JSON.parse(str) as PackageJson;
  const { name = pkg?.name, branch = '' } = options || {};

  if (!name) {
    throw new Error(`请设置项目名称`);
  }
  let hasLocalUserInfo = true;
  let userInfo = getUserInfo();
  if (!userInfo?.userName || !userInfo?.password) {
    hasLocalUserInfo = false;
    userInfo = await checkAccount();
  }
  //校验账号

  //获取配置信息
  const { url, project } = await getConfig();

  if (!url) {
    throw new Error(`配置信息错误,请联系管理员`);
  }

  const { userName, password } = userInfo;
  const baseUrl = getUrlJenkins(url, userName, password);
  const jenkinsApi = new JenkinsApi(
    baseUrl,
    '',
    project?.[name]?.['branchKey'],
  );

  if (!hasLocalUserInfo) {
    const jenkinsInfo = await jenkinsApi.info();

    if (!jenkinsInfo) {
      throw new Error('账号错误');
    }

    const cache: UserInfoType = { userName, password };
    fs.writeFileSync(getFilePath(), JSON.stringify(cache), {
      flag: 'w+',
      mode: 0o777,
    });
  }

  const jenkinsName = project?.[name]?.[env];
  if (!jenkinsName) {
    throw new Error(`找不到项目${name}在jenkins上相关信息,请联系管理员`);
  }

  if (!(await jenkinsApi.exists(jenkinsName))) {
    throw new Error('项目不存在，请联系管理员');
  }

  const originBrachName = await getBranchName(branch);

  if (!originBrachName) {
    throw new Error(`请指定发布分支`);
  }

  const [exists, list] = await jenkinsApi.existsBranch(
    originBrachName,
    jenkinsName,
  );

  if (!exists) {
    throw new Error(`发布分支不存在：${originBrachName}\n${toStringify(list)}`);
  }

  const buildResult = await jenkinsApi.build(
    {
      branchName: originBrachName,
    },
    jenkinsName,
  );

  if (!buildResult) {
    throw new Error(`
        项目发布失败\n
        项目:${name}\n
        发布环境:${env}\n
        发布分支:${originBrachName}\n
   `);
  }
  console.log(`
  正在发布\n
  项目:${name}\n
  发布环境:${env}\n
  发布分支:${originBrachName}\n
 `);
  // if (log) {
  //   const lastBuild = await jenkinsApi.lastBuild(jenkinsName);
  //   jenkinsApi.getBuildLog(jenkinsName,lastBuild)
  // }
}

async function getBranchName(branchName: string): Promise<string> {
  if (branchName) {
    return branchName;
  }
  let currentBranchName = await stdoutResult('git', [
    'rev-parse',
    '--symbolic-full-name',
    '--abbrev-ref',
    'HEAD',
  ]);

  if (currentBranchName) {
    currentBranchName = currentBranchName.trim();
    return `origin/${currentBranchName}`;
  }

  return '';
}

function getUrlJenkins(url, userName, password) {
  const { hostname, port, protocol } = Url.parse(url, true);
  return `${protocol}//${userName}:${password}@${hostname}:${port ? port : ''}`;
}

async function checkAccount() {
  let useInfo: UserInfoType = null;

  if (!fs.existsSync(getFilePath())) {
    useInfo = await inputUserInfo();
  } else {
    const result = fs.readFileSync(getFilePath(), { encoding: 'utf8' });
    useInfo = JSON.parse(result || '{}');
  }

  if (!useInfo?.userName || !useInfo?.password) {
    throw new Error('用户名或密码错误');
  }
  return useInfo;
}

function getUserInfo(): UserInfoType {
  const filePath = getFilePath();

  if (!fs.existsSync(filePath)) {
    return null;
  }

  const config = fs.readFileSync(getFilePath(), 'utf-8');
  const useInfo = JSON.parse(config || '{}');

  if (useInfo?.userName && !useInfo?.password) {
    return useInfo;
  }

  return null;
}
async function inputUserInfo(): Promise<UserInfoType> {
  console.log('请登录jenkins');
  const promptConfig = [
    {
      type: 'input',
      name: 'userName',
      message: '用户名',
    },
    {
      type: 'password',
      name: 'password',
      message: '密码',
    },
  ];
  const result = await prompt(promptConfig);
  const userName = result?.userName;
  const password = result?.password;

  if (!userName || !password) {
    throw new Error('用户名或密码错误');
  }

  return { userName, password };
}
